
/* Generated by Interface Builder */

#import "OutputView.h"
#import <appkit/appkit.h>
#import "constants.h"
#import <math.h>
#import "ControlObject.h"

id parser;

void outputPoints(PointList *p)
{
	int s;
	Point *pt;
	
	for(s=gotoPointInList(p,0,&pt);s;s=gotoNextPointInList(p,&pt)) {
		("x : %f   |y: %f   |pen: %d   |colour: %f\n",pt->x,pt->y,pt->pen,pt->pencolour);
	}
}

DPSTimedEntryProc handlerfunction(DPSTimedEntry te,double now,void *userdata)
{
	[parser doEntry];
}

void doMapping(PointList *p)
{
	int t;
	Point *pt;
	int lastpen = UP;
	float lastcol = NX_LTGRAY;

	PSsetgray(NX_LTGRAY);
	PSsetlinewidth(0.0);
	for(t=gotoPointInList(p,0,&pt);(t);t=gotoNextPointInList(p,&pt)) {
		if (lastpen == DOWN)
			PSlineto(pt->x,pt->y);
		else
			PSmoveto(pt->x,pt->y);
		if (lastcol != pt->pencolour) {
			PSstroke();
			PSnewpath();
			PSmoveto(pt->x,pt->y);
			PSsetgray(pt->pencolour);
			lastcol = pt->pencolour;
		}
		lastpen = pt->pen;
	}
	PSstroke();
}

@implementation OutputView

- setItUp:sender
{
	int i;
	NXRect r;

	[self setDrawSize:(ORight-OLeft) :(OTop-OBottom)];
	[self setDrawOrigin:OLeft :OBottom];
	animating = STOPPED;
	currentFrame = 0;
	parser = self;
	stepValue = 0.0;
	maxFrame = 0;
	

	alertWindow = [sender alertWindow];
	alertText = [sender alertText];
	return self;
}

- (BOOL)gridState
{
	return GridOn;
}

- setGridState:(BOOL)newGridState
{
	oldGridOn = GridOn;
	GridOn = newGridState;
	return self;
}


- drawSelf:(const NXRect *)rects :(int)rectCount
{
	Point *pt;
	int s;
	if (animating) {
		currentFrame= currentFrame + animating;
		if (currentFrame >= maxFrame)
			currentFrame = 0;
		else if (currentFrame < 0)
			currentFrame = (maxFrame-1);
		[outputFrames[currentFrame] composite:NX_COPY toPoint:&(bounds.origin)];
	} else {
		NXEraseRect(&bounds); 
		doMapping(&stillPoints);
		}
	return self;
}	

- doStill:(ProjParam *)params :(PointList *)pts
{
	newPointList(&stillPoints);
	convertPoints(pts,&stillPoints,GridOn,params);
	[self display];
	freePointList(&stillPoints);
	return self;
}

- doEntry
{
	[self display];
	return self;
}

- setupAnimation:(ProjParam *)params :(float)step :(PointList *)pts :(int)force
{
	int i;
	float g,h,l;
	PointList outputPoints;
	char outstr[100];
	
	if ((!force) && (step == stepValue) && (params->phi1 == currentParams.phi1)
					 && (params->proj == currentParams.proj) && (params->radius == currentParams.radius)
					 && (oldGridOn == GridOn))
	 {
	 	g = ((params->lon0*180)/PI);
		h = ((currentParams.lon0*180)/PI);
		l = (h-g)/step;
		if ((l > (round(l)-0.001)) && (l < (round(l)+0.001))){
			currentFrame = -1*(round(l) + round(h/step));
			if (currentFrame < 0)
				currentFrame += maxFrame;
			if (currentFrame >= maxFrame)
				currentFrame -= maxFrame;
			return self;
		}
	}
	oldGridOn = GridOn;
	maxFrame = (360/step);
	currentParams = *params;
	stepValue = step;
	currentFrame = 0;
	[alertWindow makeKeyAndOrderFront:self];
	
	for(i = 0;(i<maxFrame);i++) {
		sprintf(outstr,"Frame %d of %d.",(i+1),maxFrame);
		[alertText setStringValue:outstr];
		newPointList(&outputPoints);
		convertPoints(pts,&outputPoints,GridOn,params);
		params->lon0 = params->lon0+((step/180)*PI);
		if (!(outputFrames[i])) {
			outputFrames[i] = [Bitmap newSize:frame.size.width :frame.size.height
								type:NX_UNIQUEBITMAP];
			[outputFrames[i] setFlip:NO];
		}
		[outputFrames[i] lockFocus];
		PSscale((frame.size.width)/(ORight-OLeft),(frame.size.height)/(OTop-OBottom));
		PStranslate(ORight,OTop);
		NXEraseRect(&bounds);
		doMapping(&outputPoints);
		[outputFrames[i] unlockFocus];
		freePointList(&outputPoints);
	}
	[alertText setStringValue:" "];
	[alertWindow close];
	return self;
}

- (int)animation
{
	return animating;
}

- stopAnimating:(float *)angle;
{
	if (animnum)
		DPSRemoveTimedEntry(animnum);
	animnum = 0;
	animating = STOPPED;
	*angle = (currentFrame*stepValue) + ((currentParams.lon0*180)/PI);
	return self;
}

- startAnimating:(int)amate
{
	animnum = DPSAddTimedEntry(rate,(DPSTimedEntryProc)handlerfunction,NULL,NX_BASETHRESHOLD);
	animating = amate;
	return self;
}

- rateChanged:(float)f
{
	rate = f;
	if (animnum) {
		DPSRemoveTimedEntry(animnum);
		animnum = DPSAddTimedEntry(rate,(DPSTimedEntryProc)handlerfunction,NULL,NX_BASETHRESHOLD);
	}
	return self;
}

- (BOOL)shouldRunPrintPanel:sender
{
	return YES;
}

- doPrint:(ProjParam *)params :(PointList *)pts
{
	int holder;
	
	holder = animating;
	animating = STOPPED;
	newPointList(&stillPoints);
	convertPoints(pts,&stillPoints,GridOn,params);
	[self  printPSCode:self];
	freePointList(&stillPoints);
	animating = holder;
	return self;
}


@end
